using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Web;

namespace PengYouClient
{
    delegate void SetDownloadState();
    delegate void CloseWindows();
    delegate void ErrorWindow();
    public partial class Publish : Form
    {
        delegate void SetDownloadState();
        SetDownloadState d_SetDownloadState;
        delegate void CloseWindows();
        CloseWindows d_CloseWindows;
        delegate void ErrorWindow();
        ErrorWindow d_ErrorWindow;

        DavContext context;
        DavRessource ressource;

        Word._Application app;
        string publishpath;
        string ress_name;

        bool publishsuccess = false;
        bool error_send = false;
        string error_reason;
        string from = "";

        Thread PublishDocumentThread;
        Thread ShowDownloadStateThread;

        public string comments = null;

        FileStream fs;

        string basedir = SettingsManager.Server_host + ":" + SettingsManager.Server_port + SettingsManager.Ressource_basedir;

        public bool Publishsuccess
        {
            get
            {
                return publishsuccess;
            }
        }

        public Publish(object app)
        {
            d_SetDownloadState = new SetDownloadState(this.SetDownloadStateMethod);
            d_CloseWindows = new CloseWindows(this.CloseWindowsMethod);
            d_ErrorWindow = new ErrorWindow(this.LaunchErrorWindow);
            this.app = (Word._Application)app;
          
            if (IsPengYouDocument() == true && GetPublishPath() == true)
            {
                if (this.basedir.EndsWith("/"))
                    this.ress_name = this.basedir + this.publishpath;
                else if (this.publishpath.StartsWith("/"))
                    this.ress_name = this.basedir + this.publishpath;
                else
                    this.ress_name = this.basedir + "/" + this.publishpath;
            }
            else
            {
                error_reason = LanguageManager.GetString("WindowPublishNotValidDoc");
                LaunchErrorWindow();
            }
            InitializeComponent();
        }

        public Publish(object app, string dst, string from)
        {
            d_SetDownloadState = new SetDownloadState(this.SetDownloadStateMethod);
            d_CloseWindows = new CloseWindows(this.CloseWindowsMethod);
            d_ErrorWindow = new ErrorWindow(this.LaunchErrorWindow);
            this.app = (Word._Application)app;

            this.ress_name = dst;
            this.from = from;
            InitializeComponent();
        }

        private void LaunchErrorWindow()
        {
            string caption = LanguageManager.GetString("WindowPublishError");
            MessageBoxButtons buttons = MessageBoxButtons.OK;
            DialogResult result;

            result = MessageBox.Show(this, this.error_reason, caption, buttons);
            if (result == DialogResult.OK)
            {
                this.PublishDocumentThread.Abort();
                this.ShowDownloadStateThread.Abort();
                this.Close();
            }
        }

        public void CloseWindowsMethod()
        {
            PublishDocumentThread.Abort();
            ShowDownloadStateThread.Abort();
            this.Close();
        }

        bool GetPublishPath()
        {
            bool success = pengyouUtils.GetWordDocumentProp(app, "PengYouBaseDir", out publishpath);
            return success;
        }

        bool IsPengYouDocument()
        {
            string prop;

            bool success = pengyouUtils.GetWordDocumentProp(app, "PengYou", out prop);
            return success;
        }

        public void SetDownloadStateMethod()
        {
            ulong fileSize = (ulong)fs.Length;
            ulong sendedBytes = ressource.sendContainer.TotalBytes;
            string state;

            state = sendedBytes.ToString();
            state += LanguageManager.GetString("WindowPublishPublishProgress");
            state += fileSize.ToString();

            if (fileSize != 0)
            {
                ulong value_long = (sendedBytes * 100) / fileSize;
                int value = Convert.ToInt32(value_long);
                if (value > this.DownloadBar.Maximum)
                    value = this.DownloadBar.Maximum;
                this.DownloadBar.Value = value;
            }
            else
                this.DownloadBar.Value = 0;

            this.DownloadState.Text = state;
        }

        public class ShowDownloadState
        {
            Publish pub;

            public ShowDownloadState(Publish pub)
            {
                this.pub = pub;
            }

            public void LauchThread()
            {
                Thread.Sleep(500);
                while (pub.publishsuccess == false && pub.error_send == false)
                {
                    pub.Invoke(pub.d_SetDownloadState);
                    Thread.Sleep(1000);
                }
                if (pub.publishsuccess == true && pub.error_send == false)
                    pub.Invoke(pub.d_CloseWindows);
                else if (pub.publishsuccess == false && pub.error_send == true)
                    pub.Invoke(pub.d_ErrorWindow);                   
            }
        }

        public class PublishDocument
        {
            Publish pub;

            public PublishDocument(Publish pub)
            {
                this.pub = pub;
            }

            public void LaunchThread()
            {
                pub.context = new DavContext(SettingsManager.Server_host, Convert.ToInt32(SettingsManager.Server_port),
                    SettingsManager.Server_user, SettingsManager.Server_pass);
                pub.ressource = new DavRessource(pub.ress_name, pub.context);
                bool fileExists = pub.ressource.FileExists();

                if (!fileExists && pub.from == "")
                {
                    pub.error_send = true;
                    pub.error_reason = "The file has been deleted or moved on the server.\nUse the Publish As functionality.";
                    return;
                }
                if (pub.from != "publishas" && pub.from != "publishasname" && fileExists)
                {
                    if (pub.ressource.CheckOut() == false)
                    {
                        pub.error_send = true;
                        pub.error_reason = pub.ressource.ResultReason;
                    }
                }
                if (pub.error_send != true)
                {
                    int lenght = (int)pub.fs.Length;
                    byte[] bytetab = new byte[lenght];
                    pub.fs.Read(bytetab, 0, lenght);
                    if (pub.ressource.SendRessource(bytetab) == false)
                    {
                        pub.error_send = true;
                        pub.error_reason = pub.ressource.ResultReason;
                    }
                    else
                        pub.publishsuccess = true;
                    if (pub.error_send != true && pub.from != "publishas" && pub.from != "publishasname" && pub.from != "publishascomment")
                    {
                        if (pub.comments != null)                        
                            pub.ressource.SetProperty("description", pub.comments);                        
                        if (pub.ressource.CheckIn() == false)
                        {
                            pub.publishsuccess = false;
                            pub.error_send = true;
                            pub.error_reason = pub.ressource.ResultReason;
                        }
                    }
                }
                if (pub.from == "publishas" || pub.from == "publishasname" || pub.from == "publishascomment")
                {
                    if (pub.ressource.PutUnderRevision() == false)
                    {
                        pub.error_send = true;
                        pub.error_reason = pub.ressource.ResultReason;
                    }
                    if (pub.ressource.CheckOut() == false)
                    {
                        pub.error_send = true;
                        pub.error_reason = pub.ressource.ResultReason;
                        pub.publishsuccess = false;
                    }
                    if (pub.error_send != true)
                    {
                        pub.ressource.SetProperty("description", pub.comments);
                        //pub.ressource.SetProperty("comment", pub.comments);
                        if (pub.ressource.CheckIn() == false)
                        {
                            pub.publishsuccess = false;
                            pub.error_send = true;
                            pub.error_reason = pub.ressource.ResultReason;
                        }
                    }
                }
            }
        }

        private void Publish_Shown(object sender, EventArgs e)
        {
            try
            {
                app.ActiveDocument.Save();
                string docpath = app.ActiveDocument.Path + "\\" + app.ActiveDocument.Name;
                string docname = app.ActiveDocument.Name;

                this.fs = new FileStream(docpath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                if (this.from != "publishasname")
                {
                    if (this.ress_name.EndsWith("/"))
                        this.ress_name += HttpUtility.UrlPathEncode(docname);
                    else
                        this.ress_name += "/" + HttpUtility.UrlPathEncode(docname);
                }
            }
            catch (Exception)
            {

            }

            PublishDocument m_th = new PublishDocument(this);
            PublishDocumentThread = new Thread(new ThreadStart(m_th.LaunchThread));
            PublishDocumentThread.Start();

            ShowDownloadState n_th = new ShowDownloadState(this);
            ShowDownloadStateThread = new Thread(new ThreadStart(n_th.LauchThread));
            ShowDownloadStateThread.Start();

            PublishDocumentThread.Join();
        }

        private void SetText()
        {
            this.Text = LanguageManager.GetString("WindowPublish");
            DownloadCancelButton.Text = LanguageManager.GetString("WindowPublishCancelButton");
        }

        private void Publish_Load(object sender, EventArgs e)
        {
            if (this.from == "")
            {
                PublishComment PublishComment_window = new PublishComment(this);
                PublishComment_window.ShowDialog();
            }
            SetText();
        }
    }
}